package com.pearl.security.multiloginreject.demo.session.redis;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.session.SessionInformation;
import org.springframework.session.FindByIndexNameSessionRepository;
import org.springframework.session.Session;
import org.springframework.session.SessionRepository;

import java.util.Date;

/**
 * @author TD
 * @version 1.0
 * @date 2024/5/15
 */
public class MySpringSessionBackedSessionInformation<S extends Session> extends SessionInformation {
    static final String EXPIRED_ATTR = MySpringSessionBackedSessionInformation.class.getName() + ".EXPIRED";
    private static final Log logger = LogFactory.getLog(MySpringSessionBackedSessionInformation.class);
    private static final String SPRING_SECURITY_CONTEXT = "SPRING_SECURITY_CONTEXT";
    private final SessionRepository<S> sessionRepository;

    MySpringSessionBackedSessionInformation(S session, SessionRepository<S> sessionRepository) {
        super(resolvePrincipal(session), session.getId(), Date.from(session.getLastAccessedTime()));
        this.sessionRepository = sessionRepository;
        Boolean expired = (Boolean)session.getAttribute(EXPIRED_ATTR);
        if (Boolean.TRUE.equals(expired)) {
            super.expireNow();
        }

    }

    private static String resolvePrincipal(Session session) {
        String principalName = (String)session.getAttribute(FindByIndexNameSessionRepository.PRINCIPAL_NAME_INDEX_NAME);
        if (principalName != null) {
            return principalName;
        } else {
            SecurityContext securityContext = (SecurityContext)session.getAttribute("SPRING_SECURITY_CONTEXT");
            return securityContext != null && securityContext.getAuthentication() != null ? securityContext.getAuthentication().getName() : "";
        }
    }

    public void expireNow() {
        if (logger.isDebugEnabled()) {
            Log var10000 = logger;
            String var10001 = this.getSessionId();
            var10000.debug("Expiring session " + var10001 + " for user '" + this.getPrincipal() + "', presumably because maximum allowed concurrent sessions was exceeded");
        }

        super.expireNow();
        S session = this.sessionRepository.findById(this.getSessionId());
        if (session != null) {
            session.setAttribute(EXPIRED_ATTR, Boolean.TRUE);
            this.sessionRepository.save(session);
        } else {
            logger.info("Could not find Session with id " + this.getSessionId() + " to mark as expired");
        }

    }
}
